package com.net.io.netty.bytebuf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;

import java.nio.charset.Charset;

/**
 * @author zhangtengfei
 * @date 2022/2/14 14:10
 */
public class ByteBufTest {

    public static void main(String[] args) {
        demo1();
        System.out.println("------------------------------------------------------");
        demo2();
        System.out.println("------------------------------------------------------");
        read();
    }

    public static void demo1() {
        /**
         * 创建一个ByteBuf
         *
         * 1. 创建对象，该对象包含一个数组arr , 是一个byte[10]
         * 2. 在netty 的buffer中，不需要使用flip 进行反转。底层维护了 readerindex 和 writerIndex
         * 3. 通过 readerindex 和  writerIndex 和  capacity， 将buffer分成三个区域
         *      0---readerindex 已经读取的区域
         *      readerindex---writerIndex ， 可读的区域
         *      writerIndex -- capacity, 可写的区域
         */
        ByteBuf buffer = Unpooled.buffer(10);

        for (int i = 0; i < 10; i++) {
            buffer.writeByte(i);
        }
        System.out.println("capacity: " + buffer.capacity()); // 10
        //输出
        System.out.println("getByte.");
        for (int i = 0; i < buffer.capacity(); i++) {
            System.out.println(buffer.getByte(i));
        }
        System.out.println("readByte.");
        for (int i = 0; i < buffer.capacity(); i++) {
            // readerIndex 自动增长
            System.out.println(buffer.readByte());
        }
        System.out.println("执行完毕");
    }

    public static void demo2() {
        // 创建ByteBuf
        ByteBuf byteBuf = Unpooled.copiedBuffer("hello,world!", Charset.forName("utf-8"));
 
        // 使用相关的方法
        if (byteBuf.hasArray()) { // true
            byte[] content = byteBuf.array();
            //将 content 转成字符串
            System.out.println(new String(content, Charset.forName("utf-8")));
            System.out.println("byteBuf: " + byteBuf);
            System.out.println(byteBuf.arrayOffset());  // 0
            System.out.println(byteBuf.readerIndex());  // 0
            System.out.println(byteBuf.writerIndex());  // 12
            System.out.println(byteBuf.capacity());     // 64

            //System.out.println(byteBuf.readByte());
            System.out.println(byteBuf.getByte(0)); // 104

            int len = byteBuf.readableBytes();
            System.out.println("len: " + len); //可读的字节数  12

            //使用for取出各个字节
            for (int i = 0; i < len; i++) {
                System.out.println((char) byteBuf.getByte(i));
            }

            //按照某个范围读取
            System.out.println(byteBuf.getCharSequence(0, 4, Charset.forName("utf-8"))); // hell
            System.out.println(byteBuf.getCharSequence(4, 6, Charset.forName("utf-8"))); // o,worl
        }
    }

    public static void read() {
        ByteBuf buffer = Unpooled.buffer(16);
        // 先写入 4 个字节
        buffer.writeBytes(new byte[]{1, 2, 3, 4});
        System.out.println(buffer);
        // 以十六进制的表示形式打印 ByteBuf 的内容
        System.out.println(ByteBufUtil.hexDump(buffer)); // 01020304
        // 再写入一个 int 整数，也是 4 个字节
        buffer.writeInt(5);
        System.out.println(buffer);
        System.out.println(ByteBufUtil.hexDump(buffer)); // 0102030400000005

        // ------------------ 读取 ------------------
        System.out.println(buffer.readByte());
        System.out.println(buffer.readByte());
        System.out.println(buffer.readByte());
        System.out.println(buffer.readByte());
        // 读过的内容，就属于废弃部分了，再读只能读那些尚未读取的部分
        System.out.println("readByte 之后：");
        System.out.println(buffer);
        System.out.println(ByteBufUtil.hexDump(buffer)); // 00000005

        // ------------------ 重复读取 ------------------
        // 如果需要重复读取 int 整数 5，怎么办？ 可以在 read 前先做个标记 mark
        buffer.markReaderIndex();
        System.out.println(buffer.readInt());
        System.out.println("readInt 之后：");
        System.out.println(buffer);
        // 重复读取
        buffer.resetReaderIndex();
        System.out.println("resetReaderIndex 之后：");
        System.out.println(buffer);

        // 还有种办法是采用 get 开头的一系列方法，这些方法不会改变 read index
        System.out.println("get 不移动 index：");
        System.out.println(buffer.getInt(buffer.readerIndex()));
        System.out.println(buffer);
    }
}
